{
 "metadata": {
  "name": ""
 },
 "nbformat": 3,
 "nbformat_minor": 0,
 "worksheets": [
  {
   "cells": [
    {
     "cell_type": "heading",
     "level": 1,
     "metadata": {
      "slideshow": {
       "slide_type": "slide"
      }
     },
     "source": [
      "Compiling Python Modules to Native Parallel Modules Using Pythran and OpenMP Annotations"
     ]
    },
    {
     "cell_type": "markdown",
     "metadata": {},
     "source": [
      "- *Serge Guelton*, \u00c9cole Normale Sup\u00e9rieure, Paris, France & T\u00e9l\u00e9com Bretagne, Plouzan\u00e9, France\n",
      "- Pierrick Brunet, T\u00e9l\u00e9com Bretagne, Plouzan\u00e9, France\n",
      "- Mehdi Amini, SILKAN INC., Los Altos, USA"
     ]
    },
    {
     "cell_type": "heading",
     "level": 2,
     "metadata": {},
     "source": [
      "Get it - PyHPC release!"
     ]
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "from IPython.display import IFrame\n",
      "IFrame(\"http://pythonhosted.org/pythran/\", 1000, 500)"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "html": [
        "\n",
        "        <iframe\n",
        "            width=\"1000\"\n",
        "            height=500\"\n",
        "            src=\"http://pythonhosted.org/pythran/\"\n",
        "            frameborder=\"0\"\n",
        "            allowfullscreen\n",
        "        ></iframe>\n",
        "        "
       ],
       "metadata": {},
       "output_type": "pyout",
       "prompt_number": 2,
       "text": [
        "<IPython.lib.display.IFrame at 0x35e1750>"
       ]
      }
     ],
     "prompt_number": 2
    },
    {
     "cell_type": "heading",
     "level": 2,
     "metadata": {},
     "source": [
      "Introduction to Pythran"
     ]
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "%%sh\n",
      "pythran --help"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "output_type": "stream",
       "stream": "stdout",
       "text": [
        "usage: pythran [-h] [-o OUTPUT_FILE] [-E] [-e] [-f flag] [-v] [-p pass] [-m machine] [-I include_dir] [-L ldflags] [-D macro_definition] [-O level] [-g] input_file\n",
        "\n",
        "pythran: a python to C++ compiler\n",
        "\n",
        "positional arguments:\n",
        "  input_file           the pythran module to compile, either a .py or a .cpp file\n",
        "\n",
        "optional arguments:\n",
        "  -h, --help           show this help message and exit\n",
        "  -o OUTPUT_FILE       path to generated file\n",
        "  -E                   only run the translator, do not compile\n",
        "  -e                   similar to -E, but does not generate python glue\n",
        "  -f flag              any compiler switch relevant to the underlying C++ compiler\n",
        "  -v                   be verbose\n",
        "  -p pass              any pythran optimization to apply before code generation\n",
        "  -m machine           any machine flag relevant to the underlying C++ compiler\n",
        "  -I include_dir       any include dir relevant to the underlying C++ compiler\n",
        "  -L ldflags           any search dir relevant to the linker\n",
        "  -D macro_definition  any macro definition relevant to the underlying C++ compiler\n",
        "  -O level             any optimization level relevant to the underlying C++ compiler\n",
        "  -g                   any debug level relevant to the underlying C++ compiler\n",
        "\n",
        "It's a megablast!\n"
       ]
      }
     ],
     "prompt_number": 3
    },
    {
     "cell_type": "heading",
     "level": 3,
     "metadata": {},
     "source": [
      "Step 1: Using Pythran to Turn Python Code into C++ Metaprograms"
     ]
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "%%file hello_world.py\n",
      "def hello(s=\"world\"):\n",
      "    print \"hello\", s"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "output_type": "stream",
       "stream": "stdout",
       "text": [
        "Overwriting hello_world.py\n"
       ]
      }
     ],
     "prompt_number": 4
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "%%sh\n",
      "pythran -e hello_world.py -o hello_world.hpp\n",
      "head -n 20 hello_world.hpp"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "output_type": "stream",
       "stream": "stdout",
       "text": [
        "#include <pythran/pythran.h>\n",
        "namespace __pythran_hello_world\n",
        "{\n",
        "  ;\n",
        "  ;\n",
        "  struct hello\n",
        "  {\n",
        "    typedef void callable;\n",
        "    template <typename argument_type0 = core::string>\n",
        "    struct type\n",
        "    {\n",
        "      typedef typename assignable<typename std::remove_cv<typename std::remove_reference<decltype(__builtin__::None)>::type>::type>::type result_type;\n",
        "    }  \n",
        "    ;\n",
        "    template <typename argument_type0 = core::string>\n",
        "    typename type<argument_type0>::result_type operator()(argument_type0 const & s= core::string(\"world\")) const\n",
        "    ;\n",
        "  }  ;\n",
        "  template <typename argument_type0 >\n",
        "  typename hello::type<argument_type0>::result_type hello::operator()(argument_type0 const & s) const\n"
       ]
      }
     ],
     "prompt_number": 5
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "%%file hello_world.cpp\n",
      "#include \"hello_world.hpp\"\n",
      "#include <iostream>\n",
      "\n",
      "using namespace __pythran_hello_world;\n",
      "\n",
      "int main(int argc, char *argv[])\n",
      "{\n",
      " if(argc == 1)\n",
      "    hello()();\n",
      " else\n",
      " {\n",
      "    std::string msg(argv[1]);\n",
      "    hello()(msg);\n",
      " }\n",
      " return 0;\n",
      "}\n",
      "    "
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "output_type": "stream",
       "stream": "stdout",
       "text": [
        "Overwriting hello_world.cpp\n"
       ]
      }
     ],
     "prompt_number": 6
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "%%sh\n",
      "INCLUDES=\"-I $HOME/.local/lib/python2.7/site-packages -I $HOME/.local/lib/python2.7/site-packages/pythran -I $HOME/.local/lib/python2.7/site-packages/pythran/pythonic++\"\n",
      "clang++ -std=c++11 $INCLUDES hello_world.cpp -o hello_world"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [],
     "prompt_number": 7
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "%%sh\n",
      "./hello_world\n",
      "./hello_world donald\n"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "output_type": "stream",
       "stream": "stdout",
       "text": [
        "hello world \n",
        "hello donald \n"
       ]
      }
     ],
     "prompt_number": 8
    },
    {
     "cell_type": "heading",
     "level": 3,
     "metadata": {},
     "source": [
      "Step 2: Using Pythran to Turn Python Code Into Native Modules"
     ]
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "%%sh\n",
      "pythran hello_world.py"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "output_type": "stream",
       "stream": "stderr",
       "text": [
        "\u001b[31mCRITICAL\u001b[39;49;0m \u001b[34mI am in trouble. Your input file does not seem to match Pythran's constraints...\n",
        "E: Pythran spec error: no pythran specification\u001b[39;49;0m\n"
       ]
      }
     ],
     "prompt_number": 9
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "%%sh\n",
      "sed -i '1 i #pythran export hello(str)' hello_world.py\n",
      "head -n 3 hello_world.py"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "output_type": "stream",
       "stream": "stdout",
       "text": [
        "#pythran export hello(str)\n",
        "def hello(s=\"world\"):\n",
        "    print \"hello\", s"
       ]
      }
     ],
     "prompt_number": 10
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "%%sh\n",
      "pythran hello_world.py\n",
      "ls hello_world.so\n",
      "python -c \"import hello_world as hw ; hw.hello('PyHPC')\""
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "output_type": "stream",
       "stream": "stdout",
       "text": [
        "hello_world.so\n",
        "hello PyHPC \n"
       ]
      }
     ],
     "prompt_number": 11
    },
    {
     "cell_type": "heading",
     "level": 3,
     "metadata": {},
     "source": [
      "Step 3: Running Numpy Code"
     ]
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "%%file arc_distance.py\n",
      "#pythran export arc_distance(float [], float[], float[], float[])\n",
      "import numpy as np\n",
      "def arc_distance(theta_1, phi_1,theta_2, phi_2):\n",
      "    \"\"\"Calculates the pairwise arc distance between all points in vector a and b.\"\"\"\n",
      "    temp = (np.sin((theta_2 - theta_1) / 2) ** 2\n",
      "            + np.cos(theta_1) * np.cos(theta_2) * np.sin((phi_2 - phi_1) / 2) ** 2)\n",
      "    distance_matrix = 2 * (np.arctan2(np.sqrt(temp), np.sqrt(1 - temp)))\n",
      "    return distance_matrix"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "output_type": "stream",
       "stream": "stdout",
       "text": [
        "Overwriting arc_distance.py\n"
       ]
      }
     ],
     "prompt_number": 12
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "%pylab inline\n",
      "import timeit"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "output_type": "stream",
       "stream": "stdout",
       "text": [
        "Populating the interactive namespace from numpy and matplotlib\n"
       ]
      }
     ],
     "prompt_number": 13
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "n = 10000000\n",
      "t0, p0, t1, p1 = random.random(n), random.random(n), random.random(n), random.random(n),"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [],
     "prompt_number": 14
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "import arc_distance as ad\n",
      "%timeit ad.arc_distance(t0, p0, t1, p1)"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "output_type": "stream",
       "stream": "stdout",
       "text": [
        "1 loops, best of 3: 2.15 s per loop\n"
       ]
      }
     ],
     "prompt_number": 15
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "%%sh\n",
      "pythran arc_distance.py -O3 -o pythran_arc_distance.so\n",
      "pythran arc_distance.py -O3 -fopenmp -o pythran_fast_arc_distance.so"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [],
     "prompt_number": 16
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "import pythran_arc_distance as pad\n",
      "%timeit pad.arc_distance(t0, p0, t1, p1)"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "output_type": "stream",
       "stream": "stdout",
       "text": [
        "1 loops, best of 3: 1.72 s per loop\n"
       ]
      }
     ],
     "prompt_number": 17
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "import pythran_fast_arc_distance as pfad\n",
      "%timeit pfad.arc_distance(t0, p0, t1, p1)"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "output_type": "stream",
       "stream": "stdout",
       "text": [
        "1 loops, best of 3: 304 ms per loop\n"
       ]
      }
     ],
     "prompt_number": 18
    },
    {
     "cell_type": "heading",
     "level": 2,
     "metadata": {},
     "source": [
      "An Introduction to OpenMP with Pythran"
     ]
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "%%file parallel_hello.py\n",
      "#pythran export parallel_hello()\n",
      "def parallel_hello():\n",
      "    #omp parallel\n",
      "    print \"hello\""
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "output_type": "stream",
       "stream": "stdout",
       "text": [
        "Overwriting parallel_hello.py\n"
       ]
      }
     ],
     "prompt_number": 19
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "import parallel_hello as ph\n",
      "ph.parallel_hello()"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "output_type": "stream",
       "stream": "stdout",
       "text": [
        "hello\n"
       ]
      }
     ],
     "prompt_number": 20
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "%%sh\n",
      "pythran parallel_hello.py -o sequential_hello.so\n",
      "pythran parallel_hello.py -fopenmp -o real_parallel_hello.so"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [],
     "prompt_number": 21
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "%%sh\n",
      "python -c 'import sequential_hello as sh ; sh.parallel_hello()'\n",
      "echo \"*********\"\n",
      "python -c 'import real_parallel_hello as ph ; ph.parallel_hello()'"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "output_type": "stream",
       "stream": "stdout",
       "text": [
        "hello \n",
        "*********\n",
        "hello hellohello \n",
        " \n",
        "\n",
        "hello \n",
        "hello \n",
        "hello \n",
        "hello \n",
        "hello \n"
       ]
      }
     ],
     "prompt_number": 22
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "%load_ext pythranmagic"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [],
     "prompt_number": 23
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "%%pythran\n",
      "#pythran export nthreads()\n",
      "def nthreads():\n",
      "    import omp\n",
      "    m = omp.get_num_threads()\n",
      "    #omp parallel shared(n)\n",
      "    #omp master\n",
      "    n = omp.get_num_threads()\n",
      "    return m, n"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [],
     "prompt_number": 24
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "nthreads()"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "metadata": {},
       "output_type": "pyout",
       "prompt_number": 25,
       "text": [
        "(1, 8)"
       ]
      }
     ],
     "prompt_number": 25
    },
    {
     "cell_type": "heading",
     "level": 3,
     "metadata": {},
     "source": [
      "Parallelizing Loops with Pythran and OpenMP"
     ]
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "%%pythran\n",
      "#pythran export pi(int)\n",
      "def pi(n):\n",
      "    s, step = 0, 1 / (1 + n)\n",
      "    for i in range(n):\n",
      "        x = (i - .5) * step\n",
      "        s += 4. / (1 + x ** 2)\n",
      "    return step * s"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [],
     "prompt_number": 26
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "n = 1000000\n",
      "%timeit pi(n)"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "output_type": "stream",
       "stream": "stdout",
       "text": [
        "100 loops, best of 3: 10 ms per loop\n"
       ]
      }
     ],
     "prompt_number": 27
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "%%pythran\n",
      "#pythran export pi(int)\n",
      "def pi(n):\n",
      "    s, step = 0, 1 / (1 + n)\n",
      "    #omp parallel for reduction(+:s)\n",
      "    for i in range(n):\n",
      "        x = (i - .5) * step\n",
      "        s += 4. / (1 + x ** 2)\n",
      "    return step * s"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [],
     "prompt_number": 28
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "%timeit pi(n)"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "output_type": "stream",
       "stream": "stdout",
       "text": [
        "1000 loops, best of 3: 1.39 ms per loop\n"
       ]
      }
     ],
     "prompt_number": 29
    },
    {
     "cell_type": "heading",
     "level": 3,
     "metadata": {},
     "source": [
      "Parallelizing with Tasks"
     ]
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "import numpy as np\n",
      "def nested_loop(a):\n",
      "    n = a.shape[0]\n",
      "    b = np.zeros((n,n))\n",
      "    for i in range(n):\n",
      "        for j in range(i):\n",
      "            b[i,j] = np.cos(i * j)\n",
      "    return b"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [],
     "prompt_number": 30
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "n = 400\n",
      "r = random.random(n)\n",
      "%timeit nested_loop(r)"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "output_type": "stream",
       "stream": "stdout",
       "text": [
        "1 loops, best of 3: 206 ms per loop\n"
       ]
      }
     ],
     "prompt_number": 31
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "%%pythran\n",
      "#pythran export nested_loop(float [])\n",
      "import numpy as np\n",
      "def nested_loop(a):\n",
      "    n = a.shape[0]\n",
      "    b = np.zeros((n,n))\n",
      "    #omp parallel for\n",
      "    for i in range(n):\n",
      "        for j in range(i):\n",
      "            #omp task\n",
      "            b[i,j] = np.cos(i * j)\n",
      "    return b"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [],
     "prompt_number": 32
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "%timeit nested_loop(r)"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "output_type": "stream",
       "stream": "stdout",
       "text": [
        "10 loops, best of 3: 26.9 ms per loop\n"
       ]
      }
     ],
     "prompt_number": 33
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "%%pythran\n",
      "#pythran export nested_loop(float [])\n",
      "import numpy as np\n",
      "def nested_loop(a):\n",
      "    n = a.shape[0]\n",
      "    b = np.zeros((n,n))\n",
      "    #omp parallel\n",
      "    #omp single\n",
      "    for i in range(n):\n",
      "        for j in range(i):\n",
      "            #omp task\n",
      "            b[i,j] = np.cos(i * j)\n",
      "    return b"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [],
     "prompt_number": 34
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "%timeit nested_loop(r)"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "output_type": "stream",
       "stream": "stdout",
       "text": [
        "10 loops, best of 3: 15.9 ms per loop\n"
       ]
      }
     ],
     "prompt_number": 35
    },
    {
     "cell_type": "heading",
     "level": 3,
     "metadata": {},
     "source": [
      "Parallelizing Complex reductions"
     ]
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "import numpy as np\n",
      "def minmax(arr):\n",
      "    n, m = arr.shape\n",
      "    mini, maxi = np.inf, -np.inf\n",
      "    for i in range(n):\n",
      "        for j in range(m):\n",
      "            mini = min(mini, arr[i, j])\n",
      "            maxi = max(maxi, arr[i, j])\n",
      "    return mini, maxi"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [],
     "prompt_number": 36
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "n = 1000\n",
      "r = random.random((n,n))\n",
      "minmax(r)"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "metadata": {},
       "output_type": "pyout",
       "prompt_number": 37,
       "text": [
        "(5.6717835938968619e-07, 0.99999986590219125)"
       ]
      }
     ],
     "prompt_number": 37
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "%timeit minmax(r)"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "output_type": "stream",
       "stream": "stdout",
       "text": [
        "1 loops, best of 3: 680 ms per loop\n"
       ]
      }
     ],
     "prompt_number": 38
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "%%pythran\n",
      "import numpy as np\n",
      "#pythran export minmax(float[][])\n",
      "def minmax(arr):\n",
      "    n, m = arr.shape\n",
      "    mini, maxi = np.inf, -np.inf\n",
      "    #omp parallel private(lmini, lmaxi)\n",
      "    if 1:\n",
      "        lmini, lmaxi = np.inf, -np.inf\n",
      "        #omp for\n",
      "        for i in range(n):\n",
      "            for j in range(m):\n",
      "                lmini = min(lmini, arr[i, j])\n",
      "                lmaxi = max(lmaxi, arr[i, j])\n",
      "        #omp critical\n",
      "        if 1:\n",
      "            mini = min(lmini, mini)\n",
      "            maxi = max(lmaxi, maxi)\n",
      "    return mini, maxi"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [],
     "prompt_number": 39
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "minmax(r)"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "metadata": {},
       "output_type": "pyout",
       "prompt_number": 40,
       "text": [
        "(5.671783593896862e-07, 0.9999998659021913)"
       ]
      }
     ],
     "prompt_number": 40
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "%timeit minmax(r)"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "output_type": "stream",
       "stream": "stdout",
       "text": [
        "1000 loops, best of 3: 224 \u00b5s per loop\n"
       ]
      }
     ],
     "prompt_number": 41
    },
    {
     "cell_type": "heading",
     "level": 3,
     "metadata": {},
     "source": [
      "Integration with Iterators"
     ]
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "%%pythran\n",
      "#pythran export enum(str list)\n",
      "def enum(l):\n",
      "    out = 0\n",
      "    #omp parallel for\n",
      "    for i, v in enumerate(l):\n",
      "        if len(v) == i:\n",
      "            #omp atomic\n",
      "            out += 1\n",
      "    return out"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [],
     "prompt_number": 43
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "enum(['Say', 'Hello', 'to', 'PyHPC', 'from', 'Denver'])"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "metadata": {},
       "output_type": "pyout",
       "prompt_number": 44,
       "text": [
        "2"
       ]
      }
     ],
     "prompt_number": 44
    },
    {
     "cell_type": "heading",
     "level": 2,
     "metadata": {},
     "source": [
      "Validation"
     ]
    },
    {
     "cell_type": "markdown",
     "metadata": {},
     "source": [
      "- An OpenMP 3.1 validation test suite, C. Wang, S. Chandrasekaran and B. M. Chapman in _8th International Workshop on OpenMP_"
     ]
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "IFrame(\"http://numfocus.github.io/python-benchmarks/\", 1000, 1000)"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "html": [
        "\n",
        "        <iframe\n",
        "            width=\"1000\"\n",
        "            height=1000\"\n",
        "            src=\"http://numfocus.github.io/python-benchmarks/\"\n",
        "            frameborder=\"0\"\n",
        "            allowfullscreen\n",
        "        ></iframe>\n",
        "        "
       ],
       "metadata": {},
       "output_type": "pyout",
       "prompt_number": 45,
       "text": [
        "<IPython.lib.display.IFrame at 0x2feb3810>"
       ]
      }
     ],
     "prompt_number": 45
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "%%pythran bye.py\n",
      "#pythran export bye(int)\n",
      "import math\n",
      "def bye(n=3):\n",
      "    radii   = [i * n for i in [1, 3, 6]]\n",
      "    ranges  = [list(range(-r, r+1)) for r in radii]\n",
      "    squares = [[ (x,y) for x in rnge for y in rnge] for rnge in ranges]\n",
      "    circles = [[ (x,y) for x,y in sqrpoints if math.hypot(x,y) <= radius ]for sqrpoints, radius in zip(squares, radii)]\n",
      "    m = {(x,y):' ' for x,y in squares[-1]}\n",
      "    for x,y in circles[-1]:\n",
      "        m[x,y] = '*'\n",
      "    for x,y in circles[-1]:\n",
      "        if x>0: m[(x,y)] = '.'\n",
      "    for x,y in circles[-2]:\n",
      "        m[(x,y+3*n)] = '*'\n",
      "        m[(x,y-3*n)] = '.'\n",
      "    for x,y in circles[-3]:\n",
      "        m[(x,y+3*n)] = '.'\n",
      "        m[(x,y-3*n)] = '*'\n",
      "    return '\\n'.join(''.join(m[(x,y)] for x in reversed(ranges[-1])) for y in ranges[-1])"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [],
     "prompt_number": 46
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "print bye(5)"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "output_type": "stream",
       "stream": "stdout",
       "text": [
        "                              .                              \n",
        "                       .............**                       \n",
        "                    ..................***                    \n",
        "                 .......................****                 \n",
        "                .........................****                \n",
        "              ............................*****              \n",
        "            ...............................******            \n",
        "           ................................*******           \n",
        "          ..................................*******          \n",
        "         ...................................********         \n",
        "        ......................*..............********        \n",
        "       ....................*******...........*********       \n",
        "      ....................*********..........**********      \n",
        "      ....................*********..........**********      \n",
        "     .....................*********..........***********     \n",
        "     ....................***********..........**********     \n",
        "    ......................*********..........************    \n",
        "   .......................*********..........*************   \n",
        "   .......................*********..........*************   \n",
        "   ........................*******...........*************   \n",
        "  ............................*..............**************  \n",
        "  ..........................................***************  \n",
        "  ..........................................***************  \n",
        " ..........................................***************** \n",
        " ..........................................***************** \n",
        " .........................................****************** \n",
        " ........................................******************* \n",
        " .......................................******************** \n",
        " .....................................********************** \n",
        " ...................................************************ \n",
        "...............................******************************\n",
        " ........................*********************************** \n",
        " ......................************************************* \n",
        " ....................*************************************** \n",
        " ...................**************************************** \n",
        " ..................***************************************** \n",
        " .................****************************************** \n",
        " .................****************************************** \n",
        "  ...............******************************************  \n",
        "  ...............******************************************  \n",
        "  ..............**************.****************************  \n",
        "   .............***********.......************************   \n",
        "   .............**********.........***********************   \n",
        "   .............**********.........***********************   \n",
        "    ............**********.........**********************    \n",
        "     ..........**********...........********************     \n",
        "     ...........**********.........*********************     \n",
        "      ..........**********.........********************      \n",
        "      ..........**********.........********************      \n",
        "       .........***********.......********************       \n",
        "        ........**************.**********************        \n",
        "         ........***********************************         \n",
        "          .......**********************************          \n",
        "           .......********************************           \n",
        "            ......*******************************            \n",
        "              .....****************************              \n",
        "                ....*************************                \n",
        "                 ....***********************                 \n",
        "                    ...******************                    \n",
        "                       ..*************                       \n",
        "                              *                              \n"
       ]
      }
     ],
     "prompt_number": 47
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [],
     "language": "python",
     "metadata": {},
     "outputs": []
    }
   ],
   "metadata": {}
  }
 ]
}